package com.ybkj.daijia.api.weixin;

import com.google.gson.Gson;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ConnectException;
import java.net.URL;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.json.JSONException;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class WeixinUtil {

    public final static String WX_URL = "http://wx.xiaoka.me";
    public final static String access_token_url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s";
    public final static String menu_create_url = "https://api.weixin.qq.com/cgi-bin/menu/create?access_token=%s";
    public final static String user_openid_url = "https://api.weixin.qq.com/sns/jscode2session";
    /**
     * 发送客服消息
     */
    public final static String message_send_text = "https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token=%s";
    /**
     * 获取模版消息id
     */
    public final static String get_template_msg_id = "https://api.weixin.qq.com/cgi-bin/template/api_add_template?access_token=%s";
    /**
     * 发送模版消息id
     */
    public final static String send_template_msg = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=%s";
    /**
     * 获取用户基本信息
     */
    public final static String get_wx_user_info = "https://api.weixin.qq.com/cgi-bin/user/info?access_token=%s&openid=%s&lang=zh_CN";
    /**
     * 消息模版 审核
     * <p>
     * {{first.DATA}} 审核结果：{{keyword1.DATA}} 原因选项：{{keyword2.DATA}} 审核结束时间：{{keyword3.DATA}}
     * {{remark.DATA}}
     */
    public final static String TEMPLATE_MSG_AUDIT_SUCCESS = "OPENTM411211455";
    /**
     * 消息模版 审核
     * <p>
     * {{first.DATA}} 审核类型：{{keyword1.DATA}} 审核结果：{{keyword2.DATA}} 审核时间：{{keyword3.DATA}}
     * {{remark.DATA}}
     */
    public final static String TEMPLATE_MSG_AUDIT_FAILED = "OPENTM207253508";
    public static String TEMPLATE_MSG_AUDIT_SUCCESS_ID = "";
    public static String TEMPLATE_MSG_AUDIT_FAILED_ID = "";
    public static AccessToken accessToken_global;
    private static Logger log = LoggerFactory.getLogger(WeixinUtil.class);

    /**
     * 发起https请求并获取结果
     *
     * @param requestUrl 请求地址
     * @param method     请求方式（GET、POST）
     * @param params     提交的数据
     * @return JSONObject(通过JSONObject.get ( key)的方式获取json对象的属性值)
     */
    public static JSONObject httpRequest(String requestUrl, String method, String params) {
        JSONObject jsonObject = null;
        try {
            // 创建SSLContext对象，并使用我们指定的信任管理器初始化
            TrustManager[] tm = {new DefaultTrustManager()};
            SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");
            sslContext.init(null, tm, new java.security.SecureRandom());
            // 从上述SSLContext对象中得到SSLSocketFactory对象
            SSLSocketFactory ssf = sslContext.getSocketFactory();

            URL url = new URL(requestUrl);
            HttpsURLConnection httpUrlConn = (HttpsURLConnection) url.openConnection();
            httpUrlConn.setSSLSocketFactory(ssf);

            httpUrlConn.setDoOutput(true);
            httpUrlConn.setDoInput(true);
            httpUrlConn.setUseCaches(false);
            httpUrlConn.setConnectTimeout(3 * 1000);//3s
            httpUrlConn.setReadTimeout(3 * 1000);//3s
            // 设置请求方式（GET/POST）
            httpUrlConn.setRequestMethod(method);

            if ("GET".equalsIgnoreCase(method)) {
                httpUrlConn.connect();
            }

            // 当有数据需要提交时
            if (null != params) {
                OutputStream outputStream = httpUrlConn.getOutputStream();
                // 注意编码格式，防止中文乱码
                outputStream.write(params.getBytes("UTF-8"));
                outputStream.close();
                IOUtils.closeQuietly(outputStream);
            }

            // 将返回的输入流转换成字符串
            InputStream inputStream = httpUrlConn.getInputStream();
            String str = IOUtils.toString(inputStream, "utf-8");
            // 释放资源
            IOUtils.closeQuietly(inputStream);

            httpUrlConn.disconnect();
            jsonObject = new JSONObject(str);

        } catch (ConnectException ce) {
            if (log.isErrorEnabled()) {
                log.error("Weixin server connection timed out.");
            }
        } catch (Exception e) {
            if (log.isErrorEnabled()) {
                log.error("https request error:{}", e);
            }
        }
        return jsonObject;
    }

    /**
     * 获取微信 accessToken
     *
     * @param appid
     * @param appsecret
     * @return
     */
    public static AccessToken getAccessToken(String appid, String appsecret) {

        AccessToken accessToken = accessToken_global;
        if (null != accessToken && ((System.currentTimeMillis() - accessToken.getDeathTime()) < 0)) {
            return accessToken;
        }

        String requestUrl = String.format(access_token_url, appid, appsecret);

        JSONObject jsonObject = httpRequest(requestUrl, "GET", null);

        // 如果请求成功
        if (null != jsonObject) {

            try {

                accessToken = new AccessToken();
                accessToken.setToken(jsonObject.optString("access_token"));
                accessToken.setExpiresIn(jsonObject.optInt("expires_in"));
                accessToken
                    .setDeathTime(System.currentTimeMillis() + (accessToken.getExpiresIn() * 1000));

                accessToken_global = accessToken;

            } catch (JSONException e) {
                accessToken = null;
                // 获取token失败
                if (log.isErrorEnabled()) {
                    log.error("获取token失败 errcode:{} errmsg:{}",
                        jsonObject.optInt("errcode"),
                        jsonObject.optString("errmsg"));
                }
            }
        }
        return accessToken;
    }

    /**
     * 获取用户基本信息
     *
     * @param appid
     * @param appsecret
     * @param openId
     * @return
     */
    public static Map<String, Object> getWxUserInfo(String appid, String appsecret, String openId) {

        Integer errcode = 0;
        Map<String, Object> map = new HashMap<>();

        AccessToken accessToken = getAccessToken(appid, appsecret);
        if (null != accessToken) {
            String requestUrl = String.format(get_wx_user_info, accessToken.getToken(), openId);

            JSONObject jo = httpRequest(requestUrl, "GET", null);

            try {
                errcode = jo.getInt("errcode");
            } catch (JSONException e) {
//          e.printStackTrace();
            }

            map.put("errcode", errcode);

            if (errcode == 0) {
                map.put("headimgurl", jo.getString("headimgurl"));
            } else {
                map.put("errmsg", jo.getString("errmsg"));
            }

        } else {
            map.put("errcode", errcode);
            map.put("errmsg", "AccessToken NULL");
        }

        return map;
    }

    /**
     * 创建菜单
     *
     * @param jsonMenu
     * @param accessToken
     * @return int 0 成功，其他失败
     */
    public static int createMenu(String jsonMenu, String accessToken) {

        int result = 0;

        // 拼装创建菜单的url
        String url = String.format(menu_create_url, accessToken);
        // 调用接口创建菜单
        JSONObject jsonObject = httpRequest(url, "POST", jsonMenu);

        if (null != jsonObject) {
            if (0 != jsonObject.getInt("errcode")) {
                result = jsonObject.getInt("errcode");
                if (log.isErrorEnabled()) {
                    log.error("创建菜单失败 errcode:{} errmsg:{}",
                        jsonObject.getInt("errcode"),
                        jsonObject.getString("errmsg"));
                }
            }
        }

        return result;
    }

    /**
     * 小程序获取用户的openid
     *
     * @param appid     小程序appid
     * @param appsecret 小程序appsecret
     * @param jsCode    用户登陆的js_code
     * @return 从微信获取的openid
     */
    public static String getOpenid(String appid, String appsecret, String jsCode) {
        // 请求准备
        String url = user_openid_url
            + "?appid=" + appid
            + "&secret=" + appsecret
            + "&js_code=" + jsCode
            + "&grant_type=authorization_code";
        // 请求微信获取数据
        JSONObject res = httpRequest(url, "GET", null);
        if (null == res) {
            return null;
        }
        if (res.has("openid")) {
            String openid = res.getString("openid");
            return openid;
        }
        return null;
    }

    /**
     * 发送客服消息
     *
     * @param appid
     * @param appsecret
     * @param message
     * @param openId
     * @return
     */
    public static Integer sendTextMessage(String appid, String appsecret, String message,
        String openId) {
        Integer errcode = null;
        AccessToken accessToken = getAccessToken(appid, appsecret);
        if (null != accessToken) {
            try {
                String url = String.format(message_send_text, accessToken.getToken());

                Map<String, Object> paramsMap = new HashMap<String, Object>();
                paramsMap.put("touser", openId);
                paramsMap.put("msgtype", "text");

                Map<String, String> textMap = new HashMap<String, String>();
                textMap.put("content", message);

                paramsMap.put("text", textMap);

                Gson gson = new Gson();
                String params = gson.toJson(paramsMap);

                JSONObject jsonObject = httpRequest(url, "POST", params);

                errcode = jsonObject.getInt("errcode");
                //40003 openId不正确
                //45015 用户已经超过24小时没有和公众号发生交互

            } catch (Exception e) {

                e.printStackTrace();
            }

        }
        return errcode;
    }

    /**
     * 发送模版消息
     *
     * @param appid
     * @param appsecret
     * @param message
     * @param openId
     * @param weixinManagerSetting
     * @param redirectUrl
     * @return
     */
    public static String sendTemplateTextMessage(String templateNo, String appid, String appsecret,
        String openId, String redirectUrl,
        String first, String keynote1, String keynote2, String keynote3, String remark) {

        String errmsg = "unknow";
        AccessToken accessToken = getAccessToken(appid, appsecret);
        if (null != accessToken) {

            Integer errcode = 0;
            String template_id = "";

            if (templateNo.equals(TEMPLATE_MSG_AUDIT_SUCCESS)) {
                template_id = TEMPLATE_MSG_AUDIT_SUCCESS_ID;
            } else if (templateNo.equals(TEMPLATE_MSG_AUDIT_FAILED)) {
                template_id = TEMPLATE_MSG_AUDIT_FAILED_ID;
            }

            try {

                if (StringUtils.isBlank(template_id)) {
                    String url = String.format(get_template_msg_id, accessToken.getToken());

                    Map<String, Object> paramsMap = new HashMap<String, Object>();
                    paramsMap.put("template_id_short", templateNo);

                    Gson gson = new Gson();
                    String params = gson.toJson(paramsMap);

                    JSONObject jsonObject = httpRequest(url, "POST", params);

                    errcode = jsonObject.getInt("errcode");
                    errmsg = jsonObject.getString("errmsg");
                    template_id = jsonObject.getString("template_id");

                    if (templateNo.equals(TEMPLATE_MSG_AUDIT_SUCCESS)) {
                        TEMPLATE_MSG_AUDIT_SUCCESS_ID = template_id;
                    } else if (templateNo.equals(TEMPLATE_MSG_AUDIT_FAILED)) {
                        TEMPLATE_MSG_AUDIT_FAILED_ID = template_id;
                    }
                }
//              if(true){
                if (errcode == 0) {
//                String template_id = "SWcoBYVxNjTUhQo6N-UCzAjChL7SE6L0_EEwMOHY58o";

                    String url = String.format(send_template_msg, accessToken.getToken());

                    Map<String, Object> paramsMap = new HashMap<String, Object>();
                    paramsMap.put("touser", openId);
                    paramsMap.put("template_id", template_id);
                    paramsMap.put("url", redirectUrl);

                    Map<String, Object> dataMap = new HashMap<String, Object>();

                    //头部
                    Map<String, String> firstMap = new HashMap<String, String>();
                    firstMap.put("value", first);

                    //审核类型
                    Map<String, String> keynote1Map = new HashMap<String, String>();
                    keynote1Map.put("value", keynote1);

                    //审核结果
                    Map<String, String> keynote2Map = new HashMap<String, String>();
                    keynote2Map.put("value", keynote2);

                    //审核时间
                    Map<String, String> keynote3Map = new HashMap<String, String>();
                    keynote3Map.put("value", keynote3);

                    //尾部
                    Map<String, String> remarkMap = new HashMap<String, String>();
                    remarkMap.put("value", remark);

                    dataMap.put("first", firstMap);
                    dataMap.put("keyword1", keynote1Map);
                    dataMap.put("keyword2", keynote2Map);
                    dataMap.put("keyword3", keynote3Map);
                    dataMap.put("remark", remarkMap);

                    paramsMap.put("data", dataMap);

                    Gson gson = new Gson();
                    String params = gson.toJson(paramsMap);

                    JSONObject jsonObject = httpRequest(url, "POST", params);

                    errcode = jsonObject.getInt("errcode");
                    errmsg = jsonObject.getString("errmsg");

                }

            } catch (Exception e) {

                e.printStackTrace();
            }

        }
        return errmsg;
    }

    public static void main(String[] args) {

        String appid = "wxe69a4384a7915eb5";
        String appsecret = "583bbe68589fe5c4bd44fe4c46f521c9";
        String message = "aaaaaaaa";
        String openId = "oK3z0t1JH06MfVsGrXZm7CS7yNfA";

        String redirectUrl = "https://www.baidu.com/";
        String first = "您好，您提交的审核已经通过！";
        String keynote1 = "客户经理";
        String keynote2 = "审核通过";
        String keynote3 = "2017-08-29 17:17";
        String remark = "感谢您的使用";

        getWxUserInfo(appid, appsecret, openId);
        getWxUserInfo(appid, appsecret, openId);
        getWxUserInfo(appid, appsecret, openId);
        getWxUserInfo(appid, appsecret, openId);

//	  String xx= ':{"errcode":41001,"errmsg":"access_token missing hint: [GP5Zda0326vr43!]"}';

//	  sendTemplateTextMessage(appid, appsecret, openId, redirectUrl, 
//	        first, keynote1, keynote2, keynote3, remark);

    }
}
